﻿using System;
using System.Configuration;
using System.Text;
using System.Web.Mvc;
using log4net;
using Matrix.MaKaYunShang.BLL.WxInterfaceFunc;
using Matrix.MaKaYunShang.Model;
using Matrix.MaKaYunShang.Model.MatrixCloudApi;
using Matrix.Common.Utility;
using Matrix.MaKaYunShang.Model.Wechat;

namespace Matrix.MaKaYunShang.WeChat.Controllers
{
    public abstract class BaseInterfaceController : Controller
    {
        private readonly ILog _fileLog = LogManager.GetLogger(typeof(BaseInterfaceController));

        protected readonly WxInterUserFunc WxInterUserFuncObj = new WxInterUserFunc();

        protected readonly MatrixCloudCenterInterFuncBll MatrixCloudCenterInterFuncBllObj =
            new MatrixCloudCenterInterFuncBll();
        
        public MatrixCloudProjectInfo CurrentMatrixCloudProjectInfo = new MatrixCloudProjectInfo();
        public MxApiWechatInfo CurrentWechatInfo = new MxApiWechatInfo();

        #region BaseAction

        /// <summary>
        /// 获取当前接口当前云迈云项目资料
        /// </summary>
        /// <param name="pjCode"></param>
        /// <returns></returns>
        public Result<MatrixCloudProjectInfo> GetCurrentMatrixCloudProjectInfo(string pjCode)
        {
            var checkResult =
                    MatrixCloudCenterInterFuncBllObj.CheckAndGetMatrixCloudProjectInfo(pjCode);
            if (checkResult.Status)
            {
                CurrentMatrixCloudProjectInfo = checkResult.Data;
            }
            return checkResult;
        }

        public ActionResult CheckSingatureProcess(string pjCode, string wxSignatureToken)
        {
            if (Request.QueryString["nonce"] != null && !string.IsNullOrWhiteSpace(Request.QueryString["nonce"]) &&
                Request.QueryString["timestamp"] != null && !string.IsNullOrWhiteSpace(Request.QueryString["timestamp"]) &&
                Request.QueryString["signature"] != null && !string.IsNullOrWhiteSpace(Request.QueryString["signature"]) &&
                Request.QueryString["echostr"] != null && !string.IsNullOrWhiteSpace(Request.QueryString["echostr"]))
            {
                return RedirectToAction("CheckSignature", pjCode,
                    new
                    {
                        signatureToken = wxSignatureToken,
                        signature = Request.QueryString["signature"],
                        timestamp = Request.QueryString["timestamp"],
                        nonce = Request.QueryString["nonce"],
                        echostr = Request.QueryString["echostr"]
                    });
            }
            return null;
        }

        /// <summary>
        /// 公众号签名验证
        /// </summary>
        /// <param name="signatureToken"></param>
        /// <param name="signature"></param>
        /// <param name="timestamp"></param>
        /// <param name="nonce"></param>
        /// <param name="echostr"></param>
        /// <returns></returns>
        public string CheckSignatureFunc(string signatureToken, string signature, string timestamp, string nonce,
            string echostr)
        {
            if (Request.Url == null)
            {
                return string.Empty;
            }

            var strUrl = Request.Url.AbsoluteUri;
#if DEBUG
            _fileLog.Info("BaseInterfaceController | CheckSignatureFunc | " + strUrl);
#endif

            if (Request.HttpMethod.ToLower() == "post")
            {
                var s = System.Web.HttpContext.Current.Request.InputStream;
                var b = new byte[s.Length];
                s.Read(b, 0, (int)s.Length);
                var strPostValue = Encoding.UTF8.GetString(b);
                if (!string.IsNullOrEmpty(strPostValue))
                {
                    return strPostValue;
                }
            }
            else
            {
                if (WxInterUserFuncObj.ValidateSignature(signature, timestamp, nonce, signatureToken))
                {
                    if (!string.IsNullOrWhiteSpace(echostr))
                    {
                        return echostr;
                    }
                }
                else
                {
                    return echostr + " False";
                }
            }

            return string.Empty;
        }

        /// <summary>
        /// 第三方登录验证接口
        /// </summary>
        /// <param name="callBackUrlEncode"></param>
        /// <returns></returns>
        public string WxOAutherizeFunc(string callBackUrlEncode)
        {
            if (Request.Url == null)
            {
                return string.Empty;
            }

#if DEBUG
            _fileLog.Info("BaseInterfaceController | WxOAutherizeFunc Client Url " + Request.Url);
            _fileLog.Info("BaseInterfaceController | WxOAutherizeFunc Client Parameter - " + callBackUrlEncode);
#endif

            var nWxOAutherizeIndex = Request.RawUrl.IndexOf("/WxOAutherize", StringComparison.Ordinal);
            var strInterfaceMidPath = Request.RawUrl.Substring(0, nWxOAutherizeIndex);
            var strRedirectUrlSource = "http://" + Request.Url.Host + strInterfaceMidPath +
                                       "/WxAuthUserToken?authcallback=" +
                                       EncryptionLib.Encrypt(callBackUrlEncode, Encoding.UTF8);
#if DEBUG
            _fileLog.Info("BaseInterfaceController | WxOAutherizeFunc | Redirect Url " + strRedirectUrlSource);
#endif

            var wechatInfoResult = MatrixCloudCenterInterFuncBllObj.GetWechatInfo(CurrentMatrixCloudProjectInfo.PjMcId,
                CurrentMatrixCloudProjectInfo.PjSecret);
            if (!wechatInfoResult.Status)
            {
                _fileLog.Error("BaseInterfaceController | WxOAutherizeFunc| None wechat info exist.");
                return string.Empty;
            }

            var strRedirectUrl = System.Web.HttpContext.Current.Server.UrlEncode(strRedirectUrlSource);
            const string strWxUserAuthCodeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";

            var strAuthUrl = string.Format(strWxUserAuthCodeUrl, wechatInfoResult.Data.AppId, strRedirectUrl);

#if DEBUG
            _fileLog.Info("BaseInterfaceController | WxOAutherizeFunc Request Url " + strAuthUrl);
#endif

            return strAuthUrl.Trim();
        }

        /// <summary>
        /// 微信登录验证回调接口，处理完毕并跳回验证前提供的回调地址
        /// </summary>
        /// <returns></returns>
        public MxApiWechatUser WxAuthUserTokenFunc(out string redirectUrl)
        {
            redirectUrl = string.Empty;

#if DEBUG
            _fileLog.Info("BaseInterfaceController | WxAuthUserTokenFunc Request Url " + System.Web.HttpContext.Current.Request.Url.PathAndQuery);
#endif

            #region 校验
            if (Request.QueryString["code"] == null || string.IsNullOrWhiteSpace(Request.QueryString["code"]))
            {
                _fileLog.Error("BaseInterfaceController | WxAuthUserTokenFunc| None code");
                //用户未授权
                return null;
            }

            if (Request.QueryString["authcallback"] == null || string.IsNullOrWhiteSpace(Request.QueryString["authcallback"]))
            {
                _fileLog.Error("BaseInterfaceController | WxAuthUserTokenFunc| None authcallback");
                //没有oauthcallback
                return null;
            }
            #endregion

            var strWxUserAuthCode = Request.QueryString["code"];
            var strOAuthCallBack =
                EncryptionLib.Decrypt(Request.QueryString["authcallback"], Encoding.UTF8).Replace("\0", "");
            if (string.IsNullOrWhiteSpace(strOAuthCallBack))
                return null;

            try
            {
                var wechatInfoResult =
                    MatrixCloudCenterInterFuncBllObj.GetWechatInfo(CurrentMatrixCloudProjectInfo.PjMcId,
                        CurrentMatrixCloudProjectInfo.PjSecret);
                if (!wechatInfoResult.Status || wechatInfoResult.Data == null || wechatInfoResult.Data.Id == 0)
                {
                    _fileLog.Error("BaseInterfaceController | WxAuthUserTokenFunc| None wechat info exist. " +
                                   wechatInfoResult.Message);
                    return null;
                }

                var oauthUser = WxInterUserFuncObj.GetWebAuthTokenUserInfo(wechatInfoResult.Data.AppId,
                    wechatInfoResult.Data.Secret, strWxUserAuthCode);

                if (oauthUser == null || string.IsNullOrWhiteSpace(oauthUser.openid))
                {
                    _fileLog.Error(
                        "BaseInterfaceController | WxAuthUserTokenFunc oauthUser Info : Cannot get the open id: " +
                        System.Web.HttpContext.Current.Request.Url.PathAndQuery);
                    return null;
                }

                MxApiWechatUser retWechatUserInfo;
                var wechatUserResult =
                    MatrixCloudCenterInterFuncBllObj.SyncWechatUserFullInfoFromWechatToMatrixCloud(oauthUser.openid,
                        CurrentMatrixCloudProjectInfo.PjMcId, CurrentMatrixCloudProjectInfo.PjSecret);
                if (!wechatUserResult.Status || wechatUserResult.Data == null || wechatUserResult.Data.Id == 0)
                {
                    _fileLog.Error(
                        "BaseInterfaceController | WxAuthUserTokenFunc| Wechat user info of Matrix cloud center is error." +
                        wechatUserResult.Message);
                    return null;
                }

                if (!wechatUserResult.Data.Subscribe)
                {
                    var mxApiWechatUser = new MxApiWechatUser
                    {
                        Id = wechatInfoResult.Data.Id,
                        Unionid = wechatUserResult.Data.Unionid,
                        NickName = oauthUser.nickname,
                        Sex = oauthUser.sex,
                        Province = oauthUser.province,
                        City = oauthUser.city,
                        Country = oauthUser.country,
                        Headimgurl = oauthUser.headimgurl,
                        GroupId = oauthUser.groupid,
                        AddTime = wechatUserResult.Data.AddTime,
                        IsDelete = wechatUserResult.Data.IsDelete,
                        WechatInfoId = wechatUserResult.Data.WechatInfoId,
                        WiuId = wechatUserResult.Data.WiuId,
                        WiuIsDelete = wechatUserResult.Data.WiuIsDelete,
                        OpenId = oauthUser.openid
                    };

                    var updateResult = MatrixCloudCenterInterFuncBllObj.UpdateWechatUserBaseInfo(mxApiWechatUser,
                        CurrentMatrixCloudProjectInfo.PjMcId, CurrentMatrixCloudProjectInfo.PjSecret);
                    if (!updateResult.Status)
                    {
                        _fileLog.Error(
                            "BaseInterfaceController | WxAuthUserTokenFunc| update base user info to Matrix cloud center is error." +
                            updateResult.Message);

                    }
                    retWechatUserInfo = mxApiWechatUser;
                }
                else
                {
                    retWechatUserInfo = wechatUserResult.Data;
                }

#if DEBUG
                var strUserInfo = "OPENID:" + oauthUser.openid + "<br>nickname:" + oauthUser.nickname +
                                  "<br>sex:" + oauthUser.sex + "<br>province:" + oauthUser.province + "<br>city:" +
                                  oauthUser.city + "<br>country:" + oauthUser.country + "<br>headimgurl:" +
                                  oauthUser.headimgurl;
                _fileLog.Info("BaseInterfaceController | WxAuthUserTokenFunc oauthUser Info " + strUserInfo);
#endif
                var strUserInfoBase64 = System.Web.HttpContext.Current.Server.UrlEncode(JsonTool.ObjToJson(oauthUser)).ToBase64String();

                redirectUrl = strOAuthCallBack +
                                     (strOAuthCallBack.IndexOf("?", StringComparison.Ordinal) > 0 ? "&" : "?") +
                                     "openid=" + oauthUser.openid + "&userInfo=" + strUserInfoBase64;

#if DEBUG
                _fileLog.Info("BaseInterfaceController | WxAuthUserTokenFunc oauthUser Info " + redirectUrl);
#endif

                return retWechatUserInfo;
            }
            catch (WxErrorMsgException ex)
            {
                _fileLog.Error("BaseInterfaceController | WxAuthUserTokenFunc Exception " + ex);
                ViewBag.UserInfo = ex.ToString();
            }
            catch (Exception ex)
            {
                _fileLog.Error("BaseInterfaceController | WxAuthUserTokenFunc Exception " + ex + ex.StackTrace);
                ViewBag.UserInfo = ex.ToString();
            }
            return null;
        }


        /// <summary>
        /// 处理取消关注的相关操作
        /// </summary>
        /// <param name="weChatMsgRev"></param>
        /// <param name="wechatInfo"></param>
        public abstract void UnsubscribeUser(MxApiWechatEventHistory weChatMsgRev, MxApiWechatInfo wechatInfo);

        #endregion

        #region BaseMethod

        #region Post XML Data Method
        /// <summary>
        /// 分析微信服务端POST到接口的数据，并获取公众号信息
        /// </summary>
        /// <param name="msgType"></param>
        /// <param name="jsonContent"></param>
        /// <returns></returns>
        public MxApiWechatInfo AnalysisWxPostData(out string msgType, out string jsonContent)
        {
            msgType = string.Empty;
            jsonContent = string.Empty;

            var s = System.Web.HttpContext.Current.Request.InputStream;
            if (s.Length <= 0)
            {
                _fileLog.Error("BaseInterfaceController | AnalysisWxPostData : None inputstread ");
                return null;
            }
            var b = new byte[s.Length];
            s.Read(b, 0, (int)s.Length);
            var strPostValue = Encoding.UTF8.GetString(b);

#if DEBUG
            _fileLog.Info("BaseInterfaceController | AnalysisWxPostData XMCONTENT - " + strPostValue);
#endif

            var strJson = JsonSerializerHelper.ConvertXmlToJson(strPostValue);
            strJson =
                strJson.Replace("{\"xml\":", "")
                    .Replace("{\"#cdata-section\":", "")
                    .Replace("\"},", "\",")
                    .Replace("}}}", "}");
            var dictJsonData = JsonLib.DataRowFromJson(strJson);

            if (dictJsonData["MsgType"] == null || string.IsNullOrWhiteSpace(dictJsonData["MsgType"].ToString()) ||
                dictJsonData["ToUserName"] == null || string.IsNullOrWhiteSpace(dictJsonData["ToUserName"].ToString()))
            {
                _fileLog.Error("BaseInterfaceController | AnalysisWxPostData | Incorrect posted xml data ");
                return null;
            }

            var strOriginalId = dictJsonData["ToUserName"].ToString();
            var resultWechatInfo =
                MatrixCloudCenterInterFuncBllObj.GetWechatInfo(CurrentMatrixCloudProjectInfo.PjMcId,
                    CurrentMatrixCloudProjectInfo.PjSecret);

            if (!resultWechatInfo.Status || resultWechatInfo.Data == null)
            {
                _fileLog.Error(
                    "BaseInterfaceController | AnalysisWxPostData | Cannot get WechatMp Info from Matrix-Cloud-Center - " +
                    strOriginalId);
                return null;
            }

            msgType = dictJsonData["MsgType"].ToString();
            jsonContent = strJson;

#if DEBUG
            _fileLog.Info("BaseInterfaceController | AnalysisWxPostData OriginalId - " + resultWechatInfo.Data.OriginalId);
#endif
            CurrentWechatInfo = resultWechatInfo.Data;
            return resultWechatInfo.Data;
        }
        #endregion

        #region Event methods
        /// <summary>
        /// 处理微信服务端上行的EVENT POST数据
        /// </summary>
        /// <param name="jsonContent"></param>
        /// <param name="wechatInfo"></param>
        /// <returns></returns>
        public string WxEventProcess(string jsonContent, MxApiWechatInfo wechatInfo)
        {
            if (wechatInfo == null || wechatInfo.Id <=0)
            {
                _fileLog.Error("BaseInterfaceController | WxEventProcess  wechatInfo is null");
                return string.Empty;
            }

            var jsonModelEvent = JsonTool.JsonToObj<MxApiWechatEventHistory>(jsonContent);

            try
            {
                jsonModelEvent.WechatInfoId = wechatInfo.Id;
                jsonModelEvent.EventContent = jsonContent;
                jsonModelEvent.ReceiveTime = DateTime.Now;


                var eventResult = MatrixCloudCenterInterFuncBllObj.AddEventHistoryToMatrixCloud(CurrentMatrixCloudProjectInfo.PjMcId,
                    CurrentMatrixCloudProjectInfo.PjSecret, jsonModelEvent);

                if (!eventResult.Status)
                {
                    _fileLog.Error(
                        "BaseInterfaceController | WxEventProcess|  Error - Cannot add new event data to Matrix-Cloud-Center " +
                        eventResult.Message);
                    return string.Empty;
                }
                return DealEvent(eventResult.Data, wechatInfo);
            }
            catch (Exception ex)
            {
                _fileLog.Error("BaseInterfaceController | WxEventProcess|  Error - " + ex.Message);
                return string.Empty;
            }
        }

        /// <summary>
        /// 处理事件的抽象方法
        /// </summary>
        /// <param name="wechatEventHistory"></param>
        /// <param name="wechatInfo"></param>
        /// <returns></returns>
        public abstract string DealEvent(MxApiWechatEventHistory wechatEventHistory, MxApiWechatInfo wechatInfo);

        #endregion

        #region Message methods
        /// <summary>
        /// 处理微信服务端上行的Message POST数据
        /// </summary>
        /// <param name="jsonContent"></param>
        /// <param name="wechatInfo"></param>
        /// <returns></returns>
        public string WxMsgProcess(string jsonContent, MxApiWechatInfo wechatInfo)
        {
            var jsonModelMsg = JsonTool.JsonToObj<MxApiWeChatMsgRev>(jsonContent);
            try
            {
                jsonModelMsg.WechatInfoId = wechatInfo.Id;
                jsonModelMsg.Content = jsonContent;

                var msgRevResult = MatrixCloudCenterInterFuncBllObj.AddMsgRevToMatrixCloud(CurrentMatrixCloudProjectInfo.PjMcId,
                    CurrentMatrixCloudProjectInfo.PjSecret, jsonModelMsg);

                if (!msgRevResult.Status)
                {
                    _fileLog.Error(
                        "BaseInterfaceController | WxMsgProcess|  Error - Cannot add new message received data to Matrix-Cloud-Center " +
                        msgRevResult.Message);
                    return string.Empty;
                }

                return DealMsg(msgRevResult.Data, wechatInfo);
            }
            catch (Exception ex)
            {
                _fileLog.Error("BaseInterfaceController | WxMsgProcess|  Error - " + ex.Message);
                return string.Empty;
            }
        }

        /// <summary>
        /// 处理消息的抽象方法
        /// </summary>
        /// <param name="weChatMsgRev"></param>
        /// <param name="wechatInfo"></param>
        /// <returns></returns>
        public abstract string DealMsg(MxApiWeChatMsgRev weChatMsgRev, MxApiWechatInfo wechatInfo);
        #endregion

        #region Location methods
        /// <summary>
        /// 记录微信用户的地理位置上报
        /// </summary>
        /// <param name="wechatEventHistory"></param>
        /// <param name="wechatInfo"></param>
        public void AddNewLoctationInfo(MxApiWechatEventHistory wechatEventHistory, MxApiWechatInfo wechatInfo)
        {
#if DEBUG
            _fileLog.Info("BaseInterfaceController | AddNewLoctationInfo | Begin - " + wechatEventHistory.Event);
#endif

            var wechatLoctionHistory = new MxApiWechatLocationHistory
            {
                OpenId = wechatEventHistory.FromUserName,
                WechatInfoId = wechatInfo.Id,
                Longitude = wechatEventHistory.Longitude,
                Latitude = wechatEventHistory.Latitude,
                AddTime = DateTime.Now,
                IsDelete = false
            };

            try
            {
                MatrixCloudCenterInterFuncBllObj.AddLocationHistoryToMatrixCloud(CurrentMatrixCloudProjectInfo.PjMcId,
                    CurrentMatrixCloudProjectInfo.PjSecret, wechatLoctionHistory);
            }
            catch (Exception ex)
            {
                _fileLog.Error("BaseInterfaceController | wechatEventHistory : Exception - " + ex.Message + ex.StackTrace);
            }
        }
        #endregion

        #endregion

    }
}
